<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Display a map on a webpage</title>
    <meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no">
    <link href="https://api.mapbox.com/mapbox-gl-js/v2.5.1/mapbox-gl.css" rel="stylesheet">
    <script src="https://api.mapbox.com/mapbox-gl-js/v2.5.1/mapbox-gl.js"></script>
    <script src="https://unpkg.com/@turf/turf@6.5.0/turf.min.js"></script>
    <style>
        body { margin: 0; padding: 0; }
        #map { position: absolute; top: 0; bottom: 0; width: 100%; }
        .tools {
            position: absolute;
            top: 1rem;
            right: 1rem;
            z-index: 99;
        }
    </style>
</head>
<body>
<div id="map">
</div>
<div class="tools">
    <button id="location">定位</button>
</div>
<script>
    mapboxgl.accessToken = 'pk.eyJ1IjoibHp1bml1anAwOCIsImEiOiJjajJqcmlrMTYwMDI2MzJuaXd0NmRtZTl5In0.eMIg2fpiFaDInq2YVE4_2A';
    const map = new mapboxgl.Map({
        container: 'map', // container ID
        style: 'mapbox://styles/mapbox/streets-v11', // style URL
        center: [114.0494, 22.54978898845], // starting position [lng, lat]
        zoom: 11 // starting zoom
    });

    let points = []

    const arrow = ''

    map.on('load', () => {
        map.addSource('geolocation', {
            type: 'geojson',
            data: null
        })
        map.addSource('geolocation-path', {
            type: 'geojson',
            data: null
        })
        map.addSource('geolocation-accuracy', {
            type: 'geojson',
            data: null
        })
        map.addLayer({
            'id': 'geolocation-accuracy',
            'type': 'fill',
            'source': 'geolocation-accuracy',
            'paint': {
                'fill-color': '#ff0000',
                'fill-opacity': .1
            }
        });
        map.addLayer({
            'id': 'geolocation-path',
            'type': 'line',
            'source': 'geolocation-path',
            'paint': {
                "line-color": '#0077ff',
                "line-width": 8
            }
        });
        // 添加路径上的箭头
        map.loadImage(arrow, function(error, image) {
            if (error) throw error
            map.addImage('image-arrow', image)
            map.addLayer({
                'id': 'geolocation-arrow',
                'source': 'geolocation-path',
                'type': 'symbol',
                'layout': {
                    'symbol-placement': 'line',
                    'symbol-spacing': 50,
                    'icon-image': 'image-arrow',
                    'icon-size': 0.6,
                    'icon-allow-overlap': true
                }
            })
        })
        map.addLayer({
            'id': 'geolocation',
            'type': 'circle',
            'source': 'geolocation',
            'paint': {
                'circle-color': '#ff0000',
                'circle-radius': 7
            }
        });
    })

    document.querySelector('#location').addEventListener('click', () => {
        if (navigator.geolocation){
            navigator.geolocation.getCurrentPosition(showPosition);
            navigator.geolocation.watchPosition(showPosition);
        }
    })

    function showPosition(position) {
        if(!position.coords || !position.coords.latitude) return;
        const {longitude, latitude} = position.coords
        const point = { "type": "Feature", "properties": { }, "geometry": { "type": "Point", "coordinates": [longitude, latitude] } }
        const dis = position.coords.accuracy / 1000
        const polygon = turf.circle([longitude, latitude], dis);
        map.getSource('geolocation').setData(point)
        map.getSource('geolocation-accuracy').setData(polygon)

        if(points.length === 0) points.push([longitude, latitude])
        if(points.length > 1) {
            const from = turf.point(points[points.length - 1]);
            const to = turf.point([longitude, latitude]);
            const distance = turf.distance(from, to) * 1000;
            if(distance > 100) {
                points.push([longitude, latitude])
            } else {
                points[points.length - 1] = [longitude, latitude]
            }
            map.getSource('geolocation-path').setData(turf.lineString(points))
        }
        if(points.length === 0) {
            const [xmin, ymin, xmax, ymax] = turf.bbox(polygon)
            const bbox = [[xmin, ymin], [xmax, ymax]];
            map.fitBounds(bbox, {
                padding: {top: 100, bottom: 100, left: 100, right: 100}
            });
        }
    }
</script>

</body>
</html>